class Upload
  require 'time'
  require 'fileutils'

  PATH_UPLOAD = File.join("#{RAILS_ROOT}", "public").freeze
  DOCUMENT_TYPE = [".doc", ".xls", ".pdf"]
  IMAGE_TYPE = [".png", ".jpg", ".gif"]
  MAX_FILE_SIZE_UPLOAD = 5.megabyte
  # Return type hash
  # Return hash blank with if have any error, else hash_message[:error]
  def self.validate_file(file_param, type = 0)
    template_types = self::DOCUMENT_TYPE + self::IMAGE_TYPE
    case type
      when 1
        template_types = self::DOCUMENT_TYPE
      when 2
        template_types = self::IMAGE_TYPE
    end
    hash_message = Hash.new
    hash_message[:errors] = ""
    if file_param.nil? || file_param.size == 0
        hash_message[:errors] = "File does not exist!"
    else
        hash_message[:file_name] = file_param.original_filename
        file_name = File.basename(file_param.original_filename).gsub(/[^\w._-]/, '')
        unless template_types.include?(File.extname(file_name).downcase)
            hash_message[:errors] = "File must be compatible (" << template_types.join(",") << ")"
        else
            if file_param.size > self::MAX_FILE_SIZE_UPLOAD
                hash_message[:errors] = "File size cannot be greater than #{self::MAX_FILE_SIZE_UPLOAD}"
            end
        end
    end
    hash_message
  end

  # Store file need upload from client to server.
  # Return type string
  # Return string contain full path of file created if store successful, else return string blank .
  def self.store_file(file_param, path, keep_original_name = false)
      url_file = ""
      begin
          if keep_original_name
              file_name = File.basename(file_param.original_filename)
          else
              file_name = File.basename(file_param.original_filename).gsub(/[^\w._-]/, '')
              file_name = file_name + Time.now.to_i.to_s
          end

          url_file = File.join(path, file_name)
          path_file_name = self::PATH_UPLOAD + url_file
          directory = File.dirname(path_file_name)
          Rails.logger.info "====================================================> Dir: #{directory}"
          FileUtils.mkdir_p(directory) unless File.exist?(directory) || File.directory?(directory)
          File.open(path_file_name, "wb") do |file_store|
              file_store.write(file_param.read)
          end
      rescue Exception => e
        Rails.logger.info "====================================================> ERROR: #{e.backtrace}"
          return ""
      end

      url_file
  end

  # Return boolean type.
  # True if delete successful, else return false.
  def self.delete_file(url)
      return false if url.blank?
      path_file_name = File.join(self::PATH_UPLOAD, url)
      begin
          FileUtils.remove_dir(File.dirname(path_file_name), :force => true)
      rescue Exception => e
          return false
      end
      return true
  end

  def self.full_path(url)
      self::PATH_UPLOAD + url
  end

  def self.run(file_param, model, property, url_store, type = 0)
    message = self.validate_file(file_param, type)
    model.errors.add(property, message[:errors]) unless message[:errors].blank?
    path = File.join(url_store, model.id.to_s)
    if model.errors.empty?
        file_name = self.store_file(file_param, path, true)
        if file_name.blank?
            model.errors.add(property, "Can not upoad file. Please check again.")
        else
            self.save(file_name, model, property)
            unless model.errors.empty?
                self.delete_file(file_name)
            end
        end
    else
      model.raise_on_save_failure = true
    end
  end

  def self.save(url, model, property)
      file_path_previous = model[property]
      model[property] = url
      if self.save
          self.delete_file(file_path_previous) if file_path_previous && file_path_previous.downcase != url.downcase
          return true
      else
          model[property] = file_path_previous
          return false
      end
  end

  def self.delete(model, property)
      file_path = model[property]
      model[property] = ""
      if model.save
          self.delete_file(file_path)
          return true
      else
          model[property] = file_path
          return false
      end
  end
end